home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / util / rtf.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  11KB  |  383 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import string
  5. import itertools
  6. symbols = {
  7.     '\\': '\\',
  8.     '~': ' ',
  9.     'tab': '\t',
  10.     "'7b": '{',
  11.     "'7d": '}' }
  12. rev_symbols = { }
  13. for k, v in symbols.items():
  14.     rev_symbols[v] = k
  15.  
  16. rtf_fcharsets = {
  17.     0: 'ANSI',
  18.     1: 'Default',
  19.     2: 'Symbol',
  20.     3: 'Invalid',
  21.     77: 'Mac',
  22.     128: 'shiftjis',
  23.     130: 'johab',
  24.     134: 'GB2312',
  25.     136: 'Big5',
  26.     161: 'Greek',
  27.     162: 'iso-8859-9',
  28.     163: 'cp1258',
  29.     177: 'Hebrew',
  30.     178: 'Arabic',
  31.     179: 'Arabic Traditional',
  32.     180: 'Arabic user',
  33.     181: 'Hebrew user',
  34.     186: 'Baltic',
  35.     204: 'Russian',
  36.     222: 'Thai',
  37.     238: 'Eastern European',
  38.     254: 'PC 437',
  39.     255: 'OEM' }
  40.  
  41. def tokenize(string):
  42.     tokens = []
  43.     curr_token = ''
  44.     for c in string:
  45.         if c in '\\{} \r\n':
  46.             if curr_token:
  47.                 tokens.append(curr_token)
  48.                 curr_token = ''
  49.             
  50.             if c == '\n' and tokens[-1] == '\r':
  51.                 tokens[-1] = c
  52.             else:
  53.                 tokens.append(c)
  54.         tokens[-1] == '\r'
  55.         curr_token += c
  56.     
  57.     if curr_token:
  58.         tokens.append(curr_token)
  59.     
  60.     return tokens
  61.  
  62.  
  63. class TypedString(str):
  64.     
  65.     def __repr__(self):
  66.         return '<%s %s>' % (type(self).__name__, str.__repr__(self))
  67.  
  68.  
  69.  
  70. class TypedList(list):
  71.     
  72.     def __repr__(self):
  73.         return '<%s %s>' % (type(self).__name__, list.__repr__(self))
  74.  
  75.  
  76.  
  77. class ControlNode(TypedString):
  78.     pass
  79.  
  80.  
  81. class TextNode(TypedString):
  82.     pass
  83.  
  84.  
  85. class WhitespaceNode(TypedString):
  86.     pass
  87.  
  88.  
  89. class Group(TypedList):
  90.     pass
  91.  
  92.  
  93. def compress_text(doc):
  94.     new = Group()
  95.     cur_text = []
  96.     while doc:
  97.         node = doc.pop(0)
  98.         if type(node) is WhitespaceNode:
  99.             if cur_text:
  100.                 cur_text.append(node)
  101.             
  102.         cur_text
  103.         if type(node) is TextNode:
  104.             cur_text.append(node)
  105.             continue
  106.         if type(node) is Group:
  107.             if cur_text:
  108.                 new.append(TextNode(''.join(cur_text)))
  109.             
  110.             new.append(compress_text(node))
  111.             continue
  112.     return new
  113.  
  114.  
  115. def parse(tokens):
  116.     doc = None
  117.     while tokens:
  118.         token = tokens.pop(0)
  119.         if token == '{':
  120.             if doc is None:
  121.                 doc = Group()
  122.             else:
  123.                 tokens.insert(0, '{')
  124.                 doc.append(parse(tokens))
  125.         doc is None
  126.         None if token == '}' else next not in string.ascii_letters + string.digits
  127.         if token in string.whitespace:
  128.             last = doc[-1]
  129.             if type(last) is WhitespaceNode:
  130.                 doc[-1] = WhitespaceNode(last + token)
  131.             else:
  132.                 doc.append(WhitespaceNode(token))
  133.         type(last) is WhitespaceNode
  134.         last = doc[-1]
  135.         if type(last) is TextNode:
  136.             doc[-1] = TextNode(last + token)
  137.             continue
  138.         doc.append(TextNode(token))
  139.     doc = compress_text(doc)
  140.     return doc
  141.  
  142.  
  143. def tree_to_plain(tree):
  144.     tree = tree[:]
  145.     if not tree:
  146.         return ''
  147.     
  148.     if type(tree[0]) is ControlNode and str(tree[0]) in ('\\colortbl', '\\fonttbl'):
  149.         return ''
  150.     
  151.     res = []
  152.     encoding = None
  153.     last = None
  154.     uni_replace_len = None
  155.     while tree:
  156.         node = tree.pop(0)
  157.         if type(node) is Group:
  158.             res.append(tree_to_plain(node))
  159.         
  160.         if type(node) is TextNode:
  161.             s = str(node)
  162.             if encoding is not None:
  163.                 s = s.decode(encoding)
  164.             
  165.             res.append(s)
  166.         
  167.         if type(node) is WhitespaceNode:
  168.             s = str(node)
  169.             if type(last) in (ControlNode, Group):
  170.                 s = s[1:]
  171.             
  172.             res.append(s)
  173.         
  174.         if type(node) is ControlNode:
  175.             if str(node) == '\\par':
  176.                 res.append('\n')
  177.             elif str(node).startswith('\\ansicpg'):
  178.                 
  179.                 try:
  180.                     codepage = int(str(node)[len('\\ansicpg'):].strip())
  181.                 except (ValueError, IndexError):
  182.                     e = None
  183.  
  184.                 encoding = 'cp%d' % codepage
  185.             elif str(node).startswith('\\u') and str(node)[2] in '-' + string.digits:
  186.                 if tree:
  187.                     put_back = True
  188.                     replacement_charnode = tree.pop(0)
  189.                 else:
  190.                     put_back = False
  191.                     replacement_charnode = TextNode('')
  192.                 if type(replacement_char) is not TextNode:
  193.                     if put_back:
  194.                         tree.insert(0, replacement_charnode)
  195.                     
  196.                     replacement_char = ' '
  197.                 else:
  198.                     replacement_char = str(replacement_charnode)
  199.                     if uni_replace_len is not None:
  200.                         if len(replacement_char) > uni_replace_len:
  201.                             replacement_char = replacement_char[uni_replace_len:]
  202.                             rest = replacement_char[:uni_replace_len]
  203.                             if rest:
  204.                                 tree.insert(0, TextNode(rest))
  205.                             
  206.                         
  207.                     
  208.                 
  209.                 try:
  210.                     val = int(str(node)[2:])
  211.                 except ValueError:
  212.                     val = ord(replacement_char)
  213.  
  214.                 val = abs(val) + (val < 0) * 32767
  215.                 
  216.                 try:
  217.                     res.append(unichr(val))
  218.                 except ValueError:
  219.                     res.append(replacement_char)
  220.                 except:
  221.                     None<EXCEPTION MATCH>ValueError
  222.                 
  223.  
  224.             None<EXCEPTION MATCH>ValueError
  225.         
  226.         last = node
  227.     final = ''.join(res)
  228.     return final
  229.  
  230.  
  231. def rtf_to_plain(s):
  232.     return tree_to_plain(parse(tokenize(s)))
  233.  
  234.  
  235. def make_color_table(colors):
  236.     table = Group()
  237.     table.append(ControlNode('\\colortbl'))
  238.     table.append(TextNode(';'))
  239.     for color in colors:
  240.         (r, g, b, a) = tuple(color)
  241.         table.extend((ControlNode('\\red%d' % r), ControlNode('\\green%d' % g), ControlNode('\\blue%d' % b), TextNode(';')))
  242.     
  243.     return table
  244.  
  245.  
  246. def normalize_font_family(family):
  247.     family = family.lower()
  248.     if family not in set(('nil', 'roman', 'swiss', 'modern', 'script', 'decor', 'tech')):
  249.         return 'nil'
  250.     
  251.     return family
  252.  
  253.  
  254. def make_font_table(fonts):
  255.     table = Group()
  256.     table.append(ControlNode('\\fonttbl'))
  257.     for family, font in enumerate(fonts):
  258.         table.extend((ControlNode('\\f%d' % i), ControlNode('\\' + normalize_font_family(family)), TextNode(' ' + font + ';')))
  259.     
  260.     return table
  261.  
  262.  
  263. def storage_to_tree(s):
  264.     if s.get('backgrouncolor') and s.get('foregroundcolor'):
  265.         color_table = make_color_table([
  266.             s.backgroundcolor,
  267.             s.foregroundcolor])
  268.     else:
  269.         color_table = TextNode('')
  270.     if s.get('family') and s.get('font'):
  271.         font_table = make_font_table([
  272.             (s.family, s.font)])
  273.     else:
  274.         font_table = TextNode('')
  275.     top_level = Group([
  276.         ControlNode('\\rtf1'),
  277.         ControlNode('\\ansi'),
  278.         ControlNode('\\uc1'),
  279.         color_table,
  280.         font_table])
  281.     format_group = Group([])
  282.     if font_table:
  283.         format_group.append(ControlWord('\\f1'))
  284.     
  285.     if color_table:
  286.         format_group.append(ControlWord('\\cb1'))
  287.         format_group.append(ControlWord('\\cf2'))
  288.     
  289.     if s.get('bold'):
  290.         format_group.append(ControlWord('\\b'))
  291.     
  292.     if s.get('italic'):
  293.         format_group.append(ControlWord('\\i'))
  294.     
  295.     if s.get('underline'):
  296.         format_group.append(ControlWord('\\ul'))
  297.     
  298.     if s.get('size'):
  299.         format_group.append(ControlWord('\\fs%d' % s.size * 2))
  300.     
  301.     top_level.append(format_group)
  302.     return (top_level, format_group.append)
  303.  
  304.  
  305. def storage_to_rtf(s, text):
  306.     escaped = rtf_escape(text)
  307.     (doc, add_text) = storage_to_tree(s)
  308.     add_text(escaped)
  309.     return tree_to_rtf(doc)
  310.  
  311.  
  312. def rtf_escape(node):
  313.     if isinstance(node, unicode):
  314.         s = unicode(node)
  315.         
  316.         try:
  317.             s = s.encode('ascii')
  318.         except UnicodeEncodeError:
  319.             pass
  320.         except:
  321.             None<EXCEPTION MATCH>UnicodeEncodeError
  322.         
  323.  
  324.     None<EXCEPTION MATCH>UnicodeEncodeError
  325.     s = str(node)
  326.     return ''.join((lambda .0: for c in .0:
  327. rtf_escape_chr(c))(s))
  328.  
  329.  
  330. def rtf_escape_chr(c):
  331.     if c in rev_symbols:
  332.         return '\\' + rev_symbols[c]
  333.     elif isinstance(c, unicode):
  334.         val = ord(c)
  335.         (negate, val) = divmod(val, 32767)
  336.         if negate:
  337.             val = -abs(val)
  338.         
  339.         return '\\u%d ?' % val
  340.     elif ord(c) > 127 and isinstance(c, str):
  341.         return "\\'%x" % ord(c)
  342.     else:
  343.         return str(c)
  344.  
  345.  
  346. def tree_to_rtf(tree):
  347.     res = []
  348.     res.append('{')
  349.     for node in tree:
  350.         t = type(node)
  351.         if t is Group:
  352.             res.append(tree_to_rtf(node))
  353.             continue
  354.         if t is TextNode:
  355.             res.append(rtf_escape(node))
  356.             continue
  357.         res.append(str(node))
  358.     
  359.     res.append('}')
  360.     return ''.join(res)
  361.  
  362.  
  363. def main():
  364.     for test_string, test_plain in (('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 Courier New;}}{\\colortbl ;\\red0\\green255\\blue64;}\\viewkind4\\uc1\\pard\\cf1\\b\\f0\\fs32 this is the body\\par}', 'this is the body\n'), ('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fcharset0 Arial;}{\\f1\\froman\\fprq2\\fcharset0 Bodoni;}}\\viewkind4\\uc1\\pard\\i\\f0\\fs20      first line\\par\\b second line\\par\\ul\\i0 third line\\par\\b0 fourth line\\par\\ulnone\\b bold\\par\\f1 newfont\\ul\\b0\\f0\\par}', '     first line\nsecond line\nthird line\nfourth line\nbold\nnewfont\n'), ('{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 Courier New;}}\n{\\colortbl ;\\red0\\green255\\blue64;}\n\\viewkind4\\uc1\\pard\\cf1\\b\\f0\\fs32 newline\\par\nbackslash\\\\ rawr end\\par\n}', 'newline\nbackslash\\ rawr end\n')):
  365.         parsed = parse(tokenize(test_string))
  366.         plain = tree_to_plain(parsed)
  367.         print plain
  368.         if not test_plain == plain:
  369.             print repr(test_plain)
  370.             print repr(plain)
  371.             print 
  372.         
  373.         if not test_string == tree_to_rtf(parsed):
  374.             print repr(test_string)
  375.             print repr(tree_to_rtf(parsed))
  376.             print 
  377.             continue
  378.     
  379.  
  380. if __name__ == '__main__':
  381.     print main()
  382.  
  383.